// JavaScript 共有六种数据类型：Undefined、Null、Boolean、Number、String、Object。

// 原始值转布尔
; (function () {
    return
    console.log(Boolean()) // false

    console.log(Boolean(false)) // false

    console.log(Boolean(undefined)) // false
    console.log(Boolean(null)) // false
    console.log(Boolean(+0)) // false
    console.log(Boolean(-0)) // false
    console.log(Boolean(NaN)) // false
    console.log(Boolean("")) // false

})();

// 原始值转数字
; (function () {
    return
    console.log(Number()) // +0

    console.log(Number(undefined)) // NaN
    console.log(Number(null)) // +0

    console.log(Number(false)) // +0
    console.log(Number(true)) // 1

    console.log(Number("123")) // 123
    console.log(Number("-123")) // -123
    console.log(Number("1.2")) // 1.2
    console.log(Number("000123")) // 123
    console.log(Number("-000123")) // -123

    console.log(Number("0x11")) // 17

    console.log(Number("")) // 0
    console.log(Number(" ")) // 0

    console.log(Number("123 123")) // NaN
    console.log(Number("foo")) // NaN
    console.log(Number("100a")) // NaN

    console.log(Number("3.14 abc")) // NaN 用parseFloat可以解析出来

    // Number严格判断 
    // parseInt 只解析整数，parseFloat 则可以解析整数和浮点数
    console.log(parseInt("3 abc")) // 3
    console.log(parseFloat("3.14 abc")) // 3
    console.log(parseInt("-12.34")) // -12
    console.log(parseInt("0xFF")) // 255
    console.log(parseFloat(".1")) // 0.1
    console.log(parseInt("0.1")) // 0


})();

//原始值转字符
; (function () {
    return
    console.log(String()) // 空字符串

    console.log(String(undefined)) // undefined
    console.log(String(null)) // null

    console.log(String(false)) // false
    console.log(String(true)) // true

    console.log(String(0)) // 0
    console.log(String(-0)) // 0
    console.log(String(NaN)) // NaN
    console.log(String(Infinity)) // Infinity
    console.log(String(-Infinity)) // -Infinity
    console.log(String(1)) // 1

})();


// 包装对象
// 原始值通过调用 String()、Number() 或者 Boolean() 构造函数，转换为它们各自的包装对象。
// 为了方便给字符串等, 用对应的方法和属性时,先转化成对象,使用完,然后再销毁对象


// 对象转换
; (function () {
    return
    // 布尔
    // 所有对象(包括数组和函数)都转换为 true

    //字符串和数字
    // 数组的 toString 方法将每个数组元素转换成一个字符串，并在元素之间添加逗号后合并成结果字符串。
    // 函数的 toString 方法返回源代码字符串。
    // 日期的 toString 方法返回一个可读的日期和时间字符串。
    // RegExp 的 toString 方法返回一个表示正则表达式直接量的字符串。


    console.log(({}).toString()) // [object Object]

    console.log([].toString()) // ""
    console.log([0].toString()) // 0
    console.log([1, 2, 3].toString()) // 1,2,3
    console.log((function () { var a = 1; }).toString()) // function (){var a = 1;}
    console.log((/\d+/g).toString()) // /\d+/g
    console.log((new Date(2010, 0, 1)).toString()) // Fri Jan 01 2010 00:00:00 GMT+0800 (CST)


})();

// JSON.stringify
; (function () {
    //return
    console.log(JSON.stringify(null)) // null
    console.log(JSON.stringify(undefined)) // undefined，注意这个undefined不是字符串的undefined
    console.log(JSON.stringify(true)) // true
    console.log(JSON.stringify(42)) // 42
    console.log(JSON.stringify("42")) // "42"

    // 3.undefined、任意的函数以及 symbol 值，
    // 在序列化过程中会被忽略（出现在非数组对象的属性值中时）
    // 或者被转换成 null（出现在数组中时）。
    console.log(JSON.stringify({ x: undefined, y: Object, z: Symbol("") }));
    // "{}"


    JSON.stringify([undefined, Object, Symbol("")]);
    // "[null,null,null]" 

    // 4.JSON.stringify 有第二个参数 replacer，它可以是数组或者函数，
    // 用来指定对象序列化过程中哪些属性应该被处理，哪些应该被排除。
    function replacer(key, value) {
        if (typeof value === "string") {
            return undefined;
        }
        return value;
    }

    var foo = { foundation: "Mozilla", model: "box", week: 45, transport: "car", month: 7 };
    var jsonString = JSON.stringify(foo, replacer);

    console.log(jsonString)
    // {"week":45,"month":7}

    // 5.如果一个被序列化的对象拥有 toJSON 方法，
    // 那么该 toJSON 方法就会覆盖该对象默认的序列化行为：不是那个对象被序列化，
    // 而是调用 toJSON 方法后的返回值会被序列化，例如：
    var obj = {
        foo: 'foo',
        toJSON: function () {
            return 'bar';
        }
    };
    JSON.stringify(obj);      // '"bar"'
    JSON.stringify({ x: obj }); // '{"x":"bar"}'


})();